package com.ujson.chat.server.processor;

import com.ujson.base.common.dto.Res;
import com.ujson.base.common.enums.ErrorCode;
import com.ujson.base.common.utils.EnumUtil;
import com.ujson.base.common.utils.LogUtil;
import com.ujson.base.common.utils.StringUtil;
import com.ujson.chat.common.exception.ChatException;
import com.ujson.chat.common.proto.MessageProto;
import com.ujson.chat.server.auth.UserService;
import com.ujson.chat.server.builder.LoginResponseBuilder;
import com.ujson.chat.server.handler.HeartbeatRequestHandler;
import com.ujson.chat.server.handler.LoginRequestHandler;
import com.ujson.chat.server.session.ServerSession;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * <h3>ujson-parent</h3>
 * <p>异步登录业务处理器</p>
 *
 * @author JerryLiu  a1031757312@gmail.com
 * @version 1.0
 * @date 2021-11-23 21:44
 */
@Slf4j
@Service
public class LoginProcessor {
    @Autowired
    private UserService userService;

    @Autowired
    private LoginResponseBuilder loginResponseBuilder;

    @Autowired
    private LoginRequestHandler loginRequestHandler;
    @Autowired
    private HeartbeatRequestHandler heartbeatRequestHandler;

    public void doLogin(ChannelHandlerContext ctx, MessageProto.Message msg) {
        MessageProto.LoginRequest request = msg.getLoginRequest();
        String username = request.getUsername();
        String password = request.getPassword();

        CompletableFuture<Res<Object>> async = CompletableFuture.supplyAsync(() -> {
            if (StringUtil.isBlank(username) || StringUtil.isBlank(password)) {
                throw new ChatException("username or password must be not blank.");
            }
            return userService.login(username, password);
        });
        async.whenComplete((res, ex) -> {
            MessageProto.Message response = null;
            if (Objects.isNull(ex)) {
                LogUtil.info(log, "login response.");
                ErrorCode code = EnumUtil.getEnum(ErrorCode.class, res.getCode());
                response = loginResponseBuilder.build(res, code, msg.getSequence());
                if (code.isSuccess()) {
                    LogUtil.info(log, "user: [" + username + "] login success");
                    // TODO: 登录成功后, 将登录成功的用户绑定到channel, 添加心跳处理器, 删除登录处理器
                    ServerSession.inst().bind(ctx, username);

                    ctx.channel().pipeline().addAfter("encoder", "heartbeat", heartbeatRequestHandler);
                    ctx.channel().pipeline().remove(loginRequestHandler);
                }
            } else {
                LogUtil.error(log, "login failed. " + ex);
                response = loginResponseBuilder.build(res, ErrorCode.FAIL, msg.getSequence());
            }
            ctx.channel().writeAndFlush(response);
        });
    }
}
